//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use so_proto_gen_rust::image_api::image_api_client::ImageApiClient;
use so_proto_gen_rust::image_api::*;
use tauri::{
    plugin::{Plugin, Result as PluginResult},
    AppHandle, Invoke, PageLoadPayload, Runtime, Window,
};

#[tauri::command]
async fn list_image(addr: String, request: ListImageRequest) -> Result<ListImageResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.list_image(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_all_image(addr: String, request: ListAllImageRequest) -> Result<ListAllImageResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.list_all_image(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn get_image(addr: String, request: GetImageRequest) -> Result<GetImageResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.get_image(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_image(
    addr: String,
    request: RemoveImageRequest,
) -> Result<RemoveImageResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.remove_image(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_reference(
    addr: String,
    request: ListReferenceRequest,
) -> Result<ListReferenceResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.list_reference(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn get_reference(
    addr: String,
    request: GetReferenceRequest,
) -> Result<GetReferenceResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.get_reference(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_reference(
    addr: String,
    request: RemoveReferenceRequest,
) -> Result<RemoveReferenceResponse, String> {
    let chan = crate::conn_extern_server(addr).await;
    if chan.is_err() {
        return Err(chan.err().unwrap());
    }
    let mut client = ImageApiClient::new(chan.unwrap());
    match client.remove_reference(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

pub struct ImageApiPlugin<R: Runtime> {
    invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync + 'static>,
}

impl<R: Runtime> ImageApiPlugin<R> {
    pub fn new() -> Self {
        Self {
            invoke_handler: Box::new(tauri::generate_handler![
                list_image,
                list_all_image,
                get_image,
                remove_image,
                list_reference,
                get_reference,
                remove_reference,
            ]),
        }
    }
}

impl<R: Runtime> Plugin<R> for ImageApiPlugin<R> {
    fn name(&self) -> &'static str {
        "seaotter_image_api"
    }
    fn initialization_script(&self) -> Option<String> {
        None
    }

    fn initialize(&mut self, _app: &AppHandle<R>, _config: serde_json::Value) -> PluginResult<()> {
        Ok(())
    }

    fn created(&mut self, _window: Window<R>) {}

    fn on_page_load(&mut self, _window: Window<R>, _payload: PageLoadPayload) {}

    fn extend_api(&mut self, message: Invoke<R>) {
        (self.invoke_handler)(message)
    }
}
